using Lzfy_His_Service.Services;
using Lzfy_His_Service.Services.Interfaces;
using Lzfy_His_Service.Models;
using Lzfy_His_Service.Extensions;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Serilog;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Senparc.CO2NET;
using Senparc.CO2NET.RegisterServices;
using Senparc.Weixin;
using Senparc.Weixin.RegisterServices;
using Senparc.Weixin.Work;
using Senparc.Weixin.Work.Containers;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using StackExchange.Redis;
using Microsoft.AspNetCore.DataProtection;
using System.Security.Cryptography.X509Certificates;

namespace Lzfy_His_Service;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // 配置Serilog日志
        ConfigureSerilog(builder);

        // 配置服务
        ConfigureServices(builder.Services, builder.Configuration);

        var app = builder.Build();

        // 配置中间件管道
        ConfigureMiddleware(app);

        // 配置Senparc微信服务
        ConfigureSenparcWeixin(app);

        app.Run();
    }

    /// <summary>
    /// 配置Serilog日志服务
    /// </summary>
    private static void ConfigureSerilog(WebApplicationBuilder builder)
    {
        Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(builder.Configuration)
            .Enrich.FromLogContext()
            .Enrich.WithProperty("Application", "Lzfy_His_Service")
            .Enrich.WithProperty("Environment", builder.Environment.EnvironmentName)
            .CreateLogger();

        builder.Host.UseSerilog();
    }

    /// <summary>
    /// 配置应用服务
    /// </summary>
    private static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // 基础服务配置
        services.AddControllers()
            .AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.PropertyNamingPolicy = null;
                options.JsonSerializerOptions.WriteIndented = true;
            });

        services.AddEndpointsApiExplorer();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new() { Title = "Lzfy His Service API", Version = "v1" });
            c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Lzfy_His_Service.xml"));
        });

        // CORS配置
        services.AddCors(options =>
        {
            options.AddPolicy("AllowAll", policy =>
            {
                policy.AllowAnyOrigin()
                      .AllowAnyMethod()
                      .AllowAnyHeader();
            });
        });

        // JWT认证配置
        ConfigureJwtAuthentication(services, configuration);

        // 缓存服务配置
        ConfigureCacheServices(services, configuration);

        // 数据保护服务配置
        ConfigureDataProtection(services, configuration);

        // HTTP客户端配置
        ConfigureHttpClients(services, configuration);

        // Senparc服务配置
        ConfigureSenparcServices(services, configuration);

        // 业务服务配置
        ConfigureBusinessServices(services, configuration);

        // 健康检查配置
        ConfigureHealthChecks(services, configuration);
    }

    /// <summary>
    /// 配置JWT认证
    /// </summary>
    private static void ConfigureJwtAuthentication(IServiceCollection services, IConfiguration configuration)
    {
        var jwtSettings = configuration.GetSection("JwtSettings");
        var key = Encoding.ASCII.GetBytes(jwtSettings["SecretKey"] ?? throw new InvalidOperationException("JWT SecretKey not configured"));

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.RequireHttpsMetadata = false;
            options.SaveToken = true;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = true,
                ValidIssuer = jwtSettings["Issuer"],
                ValidateAudience = true,
                ValidAudience = jwtSettings["Audience"],
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            };
        });

        services.AddAuthorization();
    }

    /// <summary>
    /// 配置缓存服务
    /// </summary>
    private static void ConfigureCacheServices(IServiceCollection services, IConfiguration configuration)
    {
        // 内存缓存
        services.AddMemoryCache(options =>
        {
            options.SizeLimit = 1000;
            options.CompactionPercentage = 0.25;
        });

        // Redis缓存配置
        var redisConnectionString = configuration.GetConnectionString("Redis");
        if (!string.IsNullOrEmpty(redisConnectionString))
        {
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = redisConnectionString;
                options.InstanceName = "Lzfy_His_Service";
            });

            // Redis连接多路复用器
            services.AddSingleton<IConnectionMultiplexer>(provider =>
            {
                var configuration = ConfigurationOptions.Parse(redisConnectionString);
                configuration.AbortOnConnectFail = false;
                configuration.ConnectRetry = 3;
                configuration.ConnectTimeout = 5000;
                configuration.SyncTimeout = 5000;
                return ConnectionMultiplexer.Connect(configuration);
            });
        }
    }

    /// <summary>
    /// 配置数据保护服务
    /// </summary>
    private static void ConfigureDataProtection(IServiceCollection services, IConfiguration configuration)
    {
        var dataProtectionBuilder = services.AddDataProtection()
            .SetApplicationName("Lzfy_His_Service")
            .SetDefaultKeyLifetime(TimeSpan.FromDays(90));

        // 如果配置了Redis，使用Redis存储密钥
        var redisConnectionString = configuration.GetConnectionString("Redis");
        if (!string.IsNullOrEmpty(redisConnectionString))
        {
            dataProtectionBuilder.PersistKeysToStackExchangeRedis(
                ConnectionMultiplexer.Connect(redisConnectionString),
                "DataProtection-Keys");
        }

        // 如果配置了证书，使用证书保护密钥
        var certificateThumbprint = configuration["DataProtection:CertificateThumbprint"];
        if (!string.IsNullOrEmpty(certificateThumbprint))
        {
            var certificate = GetCertificateFromStore(certificateThumbprint);
            if (certificate != null)
            {
                dataProtectionBuilder.ProtectKeysWithCertificate(certificate);
            }
        }
    }

    /// <summary>
    /// 配置HTTP客户端
    /// </summary>
    private static void ConfigureHttpClients(IServiceCollection services, IConfiguration configuration)
    {
        services.AddHttpClient("SenparcWeChat", client =>
        {
            client.Timeout = TimeSpan.FromSeconds(30);
            client.DefaultRequestHeaders.Add("User-Agent", "Lzfy_His_Service/1.0");
        })
        .AddPolicyHandler(GetRetryPolicy())
        .AddPolicyHandler(GetCircuitBreakerPolicy());
    }

    /// <summary>
    /// 配置Senparc服务
    /// </summary>
    private static void ConfigureSenparcServices(IServiceCollection services, IConfiguration configuration)
    {
        // 注册Senparc.CO2NET全局服务
        services.AddSenparcGlobalServices(configuration)
            .AddSenparcWeixinServices(configuration);

        // 注册自定义Senparc服务
        services.AddScoped<ISenparcWeChatService, SenparcWeChatService>();
        services.AddScoped<ISenparcCacheService, SenparcCacheService>();

        // 配置Senparc企业微信选项
        services.Configure<SenparcWeChatConfiguration>(configuration.GetSection("SenparcWeChat"));
        services.Configure<SenparcCacheConfiguration>(configuration.GetSection("SenparcWeChat:Cache"));
    }

    /// <summary>
    /// 配置业务服务
    /// </summary>
    private static void ConfigureBusinessServices(IServiceCollection services, IConfiguration configuration)
    {
        // 现有业务服务
        services.AddScoped<IAuthService, AuthService>();
        services.AddScoped<ICaptchaService, CaptchaService>();
        
        // 其他业务服务...
    }

    /// <summary>
    /// 配置健康检查
    /// </summary>
    private static void ConfigureHealthChecks(IServiceCollection services, IConfiguration configuration)
    {
        var healthChecksBuilder = services.AddHealthChecks();

        // SQL Server健康检查
        var sqlConnectionString = configuration.GetConnectionString("DefaultConnection");
        if (!string.IsNullOrEmpty(sqlConnectionString))
        {
            healthChecksBuilder.AddSqlServer(sqlConnectionString, name: "sqlserver");
        }

        // Oracle健康检查
        var oracleConnectionString = configuration.GetConnectionString("OracleConnection");
        if (!string.IsNullOrEmpty(oracleConnectionString))
        {
            healthChecksBuilder.AddOracle(oracleConnectionString, name: "oracle");
        }

        // Redis健康检查
        var redisConnectionString = configuration.GetConnectionString("Redis");
        if (!string.IsNullOrEmpty(redisConnectionString))
        {
            healthChecksBuilder.AddRedis(redisConnectionString, name: "redis");
        }

        // 企业微信健康检查
        healthChecksBuilder.AddCheck<WeChatHealthCheck>("wechat");
    }

    /// <summary>
    /// 配置中间件管道
    /// </summary>
    private static void ConfigureMiddleware(WebApplication app)
    {
        // 开发环境配置
        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "Lzfy His Service API V1");
                c.RoutePrefix = "swagger";
            });
        }

        // 全局异常处理
        app.UseExceptionHandler("/Error");
        app.UseHsts();

        // 基础中间件
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();

        // CORS
        app.UseCors("AllowAll");

        // 认证和授权
        app.UseAuthentication();
        app.UseAuthorization();

        // 健康检查
        app.UseHealthChecks("/health", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
        {
            ResponseWriter = async (context, report) =>
            {
                context.Response.ContentType = "application/json";
                var response = new
                {
                    status = report.Status.ToString(),
                    checks = report.Entries.Select(x => new
                    {
                        name = x.Key,
                        status = x.Value.Status.ToString(),
                        exception = x.Value.Exception?.Message,
                        duration = x.Value.Duration.ToString()
                    }),
                    duration = report.TotalDuration.ToString()
                };
                await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(response));
            }
        });

        // 控制器路由
        app.MapControllers();
    }

    /// <summary>
    /// 配置Senparc微信服务
    /// </summary>
    private static void ConfigureSenparcWeixin(WebApplication app)
    {
        var env = app.Environment;
        var configuration = app.Configuration;

        // 启动 CO2NET 全局注册，必须！
        IRegisterService register = RegisterService.Start(env, configuration)
            .UseSenparcGlobal()
            .UseSenparcWeixin();

        // 注册企业微信应用
        var senparcWeChatConfig = configuration.GetSection("SenparcWeChat").Get<SenparcWeChatConfiguration>();
        if (senparcWeChatConfig != null && !string.IsNullOrEmpty(senparcWeChatConfig.CorpId))
        {
            register.RegisterWorkAccount(
                senparcWeChatConfig.CorpId,
                senparcWeChatConfig.CorpSecret,
                "Lzfy_His_Service_Work");

            app.Logger.LogInformation("企业微信应用注册成功: CorpId={CorpId}, AgentId={AgentId}", 
                senparcWeChatConfig.CorpId, senparcWeChatConfig.AgentId);
        }
        else
        {
            app.Logger.LogWarning("企业微信配置不完整，跳过注册");
        }
    }

    /// <summary>
    /// 获取重试策略
    /// </summary>
    private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return Policy
            .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
            .Or<HttpRequestException>()
            .WaitAndRetryAsync(
                retryCount: 3,
                sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                onRetry: (outcome, timespan, retryCount, context) =>
                {
                    var logger = context.GetLogger();
                    logger?.LogWarning("HTTP请求重试 {RetryCount}/3，延迟 {Delay}ms", retryCount, timespan.TotalMilliseconds);
                });
    }

    /// <summary>
    /// 获取熔断策略
    /// </summary>
    private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
    {
        return Policy
            .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
            .Or<HttpRequestException>()
            .CircuitBreakerAsync(
                handledEventsAllowedBeforeBreaking: 5,
                durationOfBreak: TimeSpan.FromSeconds(30),
                onBreak: (exception, duration) =>
                {
                    // 可以添加日志记录
                },
                onReset: () =>
                {
                    // 可以添加日志记录
                });
    }

    /// <summary>
    /// 从证书存储获取证书
    /// </summary>
    private static X509Certificate2? GetCertificateFromStore(string thumbprint)
    {
        try
        {
            using var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store.Open(OpenFlags.ReadOnly);
            var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
            return certificates.Count > 0 ? certificates[0] : null;
        }
        catch (Exception ex)
        {
            Log.Warning(ex, "获取证书失败: {Thumbprint}", thumbprint);
            return null;
        }
    }
}

/// <summary>
/// 企业微信健康检查
/// </summary>
public class WeChatHealthCheck : IHealthCheck
{
    private readonly ISenparcWeChatService _weChatService;
    private readonly ILogger<WeChatHealthCheck> _logger;

    public WeChatHealthCheck(ISenparcWeChatService weChatService, ILogger<WeChatHealthCheck> logger)
    {
        _weChatService = weChatService;
        _logger = logger;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        try
        {
            // 尝试获取AccessToken来验证企业微信连接
            var accessToken = await _weChatService.GetAccessTokenAsync();
            
            if (string.IsNullOrEmpty(accessToken))
            {
                return HealthCheckResult.Unhealthy("无法获取企业微信AccessToken");
            }

            return HealthCheckResult.Healthy("企业微信服务正常");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "企业微信健康检查失败");
            return HealthCheckResult.Unhealthy("企业微信服务异常", ex);
        }
    }
}

/// <summary>
/// Polly扩展方法
/// </summary>
public static class PollyExtensions
{
    public static ILogger? GetLogger(this Context context)
    {
        if (context.TryGetValue("logger", out var logger))
        {
            return logger as ILogger;
        }
        return null;
    }
}

/*
使用说明：

1. 项目配置：
   - 确保已安装所有必需的NuGet包
   - 更新appsettings.json配置文件
   - 配置企业微信应用参数

2. 服务注册：
   - Senparc.CO2NET全局服务
   - Senparc.Weixin微信服务
   - 自定义企业微信服务
   - 缓存服务（内存+Redis）
   - HTTP客户端（含重试和熔断）

3. 中间件配置：
   - 异常处理
   - 认证授权
   - CORS跨域
   - 健康检查
   - Swagger文档

4. 安全配置：
   - JWT认证
   - 数据保护
   - HTTPS重定向
   - 证书管理

5. 监控配置：
   - Serilog结构化日志
   - 健康检查端点
   - 性能监控
   - 错误追踪

6. 部署注意事项：
   - 环境变量配置
   - 连接字符串安全
   - 证书部署
   - Redis集群配置

7. 启动顺序：
   - 配置服务 → 构建应用 → 配置中间件 → 注册微信服务 → 启动应用

8. 故障排除：
   - 检查配置文件
   - 查看健康检查状态
   - 分析日志输出
   - 验证网络连接
*/